package cyy.example.com.facotry.data;

import com.example.com.common.factory.data.DbDataSource;
import com.example.com.common.utils.ReflectUtils;

import java.lang.reflect.Type;
import java.util.LinkedList;
import java.util.List;

import cyy.example.com.facotry.model.db.BaseDbModel;
import cyy.example.com.facotry.net.helper.DbHelper;

/**
 * Created by ChenYiYao on 2018/11/30.
 * des : 基础的数据仓库，实现对数据库仓库基本监听
 */
public abstract class BaseDbRepository<Data extends BaseDbModel<Data>>
        implements DbDataSource<Data>, DbHelper.ChangedListener<Data> {

    //与presenter交互的回调
    private SucceedCallback<List<Data>> mCallback;
    private int mCallreqId;//请求回调的id
    protected final LinkedList<Data> dataList = new LinkedList<>(); // 当前缓存的数据
    private Class<Data> dataClass; // 当前范型对应的真实的Class信息

    public BaseDbRepository() {
        // 拿当前类的范型数组信息
        Type[] types = ReflectUtils.getActualTypeArguments(BaseDbRepository.class, this.getClass());
        dataClass = (Class<Data>) types[0];
    }

    @Override
    public void load(SucceedCallback<List<Data>> callback, int reqId) {
        this.mCallback = callback;
        //数据库监听操作
        registerDbChangedListener();
    }

    @Override
    public void dispose() {
        // 取消监听，销毁数据
        this.mCallback = null;
        DbHelper.removeChangedListener(dataClass, this);
        dataList.clear();
    }

    @Override
    public void onDataSave(Data... list) {
        boolean isChanged = false;
        for (Data data : list) {
            if (isRequired(data)) {
                isChanged = true;
                insertOrUpdate(data);
            }
        }

        // 有数据变更，则进行界面刷新
        if (isChanged) {
            notifyDataChange();
        }
    }

    @Override
    public void onDataDelete(Data... list) {
        // 在删除情况下不用进行过滤判断
        // 但数据库数据删除的操作
        boolean isChanged = false;
        for (Data data : list) {
            if (dataList.remove(data))
                isChanged = true;
        }

        // 有数据变更，则进行界面刷新
        if (isChanged)
            notifyDataChange();
    }

    @Override
    public void onDataQuery(Data... list) {
        if (list == null || list.length == 0) {
            dataList.clear();
            notifyDataChange();
            return;
        }
        onDataSave(list);
    }

    @Override
    public void onTableDelete() {
        boolean isChanged = false;
        if (dataList.size() > 0) {
            isChanged = true;
            dataList.clear();
        }
        if (isChanged)
            notifyDataChange();
    }

    // 插入或者更新
    protected void insertOrUpdate(Data data) {
        int index = indexOf(data);
        if (index >= 0) {
            replace(index, data);
        } else {
            insert(data);
        }
    }


    // 更新操作，更新某个坐标下的数据
    protected void replace(int index, Data data) {
        dataList.remove(index);
        dataList.add(index, data);
    }

    // 添加方法
    protected void insert(Data data) {
        dataList.add(data);
    }


    // 查询一个数据是否在当前的缓存数据中，如果在则返回坐标
    protected int indexOf(Data newData) {
        int index = -1;
        for (Data data : dataList) {
            index++;
            if (data.isSame(newData)) {
                return index;
            }
        }
        return -1;
    }


    /**
     * 判断是否需要发送通知
     *
     * @param data
     * @return
     */
    protected abstract boolean isRequired(Data data);

    /**
     * 判断是否需要发送通知
     *
     * @param data
     * @return
     */
    protected abstract boolean isRequiredCallbackBefore(List<Data> data);


    /**
     * 添加数据库的监听操作
     */
    protected void registerDbChangedListener() {
        DbHelper.addChangedListener(dataClass, this);
    }

    // 通知界面刷新的方法
    private void notifyDataChange() {
        if (isRequiredCallbackBefore(dataList)) {
            final SucceedCallback<List<Data>> callback = this.mCallback;
            //回到主线程
            callback.onDataLoaded(dataList, mCallreqId);
        }
    }

}
